package com.mycompany.crm;

import com.alibaba.fastjson.JSON;
import com.mycompany.crm.base.ResultInfo;
import com.mycompany.crm.exceptions.AuthException;
import com.mycompany.crm.exceptions.NoLoginException;
import com.mycompany.crm.exceptions.ParamsException;
import javafx.print.Printer;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 全局异常统一处理
 * @author jy
 * @version 1.0
 * @date 2022/1/5 17:21
 */
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
    /**
     *
     * 异常处理方法
     *    方法的返回值:
     *      1.返回视图
     *      2.返回数据(JSON数据)
     *
     * @param request 请求对象
     * @param response 响应对象
     * @param obj 方法对象
     * @param e 异常对象
     * @return ModelAndView 视图
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object obj, Exception e) {

        /**
         * 非法请求拦截
         * 判断是否抛出未登录异常
         *    如果抛出该异常，则要求用户登录，重定向跳转到登录页面
         */
        if (e instanceof NoLoginException){
            //重定向到登录页面
            return new ModelAndView("redirect:/index");
        }


        /**
         * 设置默认异常处理(返回视图)
         */
        ModelAndView modelAndView = new ModelAndView("error");
        //设置异常信息
        modelAndView.addObject("code",500);
        modelAndView.addObject("msg","系统异常，请重试！");

        // 判断HandlerMethod
        if (obj instanceof HandlerMethod){
            //类型转换
            HandlerMethod handlerMethod = (HandlerMethod) obj;
            //通过反射获取方法上声明的@ResponseBody注解对象
            ResponseBody responseBody =  handlerMethod.getMethod().getDeclaredAnnotation(ResponseBody.class);

            //判断responseBody对象是否为空(如果为空则返回的是视图，反之则为数据)
            if (responseBody == null){
                /**
                 * 控制方法返回的是视图
                 */
                //判断异常类型
                if (e instanceof ParamsException){
                    ParamsException p = (ParamsException) e;
                    //设置异常信息
                    modelAndView.addObject("code",p.getCode());
                    modelAndView.addObject("msg",p.getMsg());
                } else if (e instanceof AuthException){
                    AuthException a = (AuthException) e;
                    //设置异常信息
                    modelAndView.addObject("code",a.getCode());
                    modelAndView.addObject("msg",a.getMsg());
                }
                return modelAndView;
            }else {
                /**
                 * 控制方法返回的是数据
                 */
                //设置默认的异常处理
                ResultInfo resultInfo = new ResultInfo();
                resultInfo.setCode(500);
                resultInfo.setMsg("异常处理，请重试!");

                //判断异常类型是否是自定义异常
                if (e instanceof ParamsException){
                    ParamsException p = (ParamsException) e;
                    resultInfo.setCode(p.getCode());
                    resultInfo.setMsg(p.getMsg());
                } else if (e instanceof AuthException){ //认证异常
                    AuthException a = (AuthException) e;
                    resultInfo.setCode(a.getCode());
                    resultInfo.setMsg(a.getMsg());
                }

                //设置响应类型及编码格式(响应JSON格式的数据)
                response.setContentType("application/json;charset=UTF-8");
                //得到字符输出流
                PrintWriter out = null;
                try {
                    //得到输出流
                    out = response.getWriter();
                    //将需要返回的对象转换为json格式的字符
                    String json = JSON.toJSONString(resultInfo);
                    //输出
                    out.write(json);
                }catch (IOException ioe){
                    ioe.printStackTrace();
                }finally {
                    //流不为空则关闭
                    if (out != null){
                        out.close();
                    }
                }
                return null;
            }
        }
        return modelAndView;
    }
}
